/* Zhao Zongyi, xinshengzzy@foxmail.com, 2020.11.11 */
#include "tofino/stateful_alu_blackbox.p4"
#include "tofino/pktgen_headers.p4"
#include <tofino/constants.p4>
#include <tofino/intrinsic_metadata.p4>

#include "includes/headers.p4"
#include "includes/parser.p4"
#include "includes/macro.p4"
#include "includes/registers.p4"
#include "includes/tables.p4"
#include "includes/metadata.p4"
#include "includes/fieldlists.p4"



/*---------- ingress ----------*/
control ingress {
  // stage 0
  apply(forward_t);
  if (0 == m_meta.promotion) {
    // stage 0
    apply(update_M1_srcip_t);
    apply(update_M1_dstip_t);
    apply(update_M1_proto_t);
    // stage 1
    apply(update_M1_cnt_t);
    if (1 == m_meta.M1_collision) {
      // stage 2
      apply(update_M2_srcip_t);
      apply(update_M2_dstip_t);
      apply(update_M2_proto_t);
      // stage 3
      apply(update_M2_cnt_t);
      if (1 == m_meta.M2_collision) {
	// stage 4
	apply(update_M3_srcip_t);
	apply(update_M3_dstip_t);
	apply(update_M3_proto_t);
	// stage 5
	apply(update_M3_cnt_t);
	if(1 == m_meta.M3_collision) {
	  // stage 6
	  apply(update_M4_srcip_t);
	  apply(update_M4_dstip_t);
	  apply(update_M4_proto_t);
	  // stage 7
	  apply(update_M4_cnt_t);
	  if (1 == m_meta.M4_collision) {
	    // stage 8
	    apply(compare_M_cnts_t);
	    apply(gen_rand_num_t);
	    apply(set_min_t); // set_min_t and resubmit_t can be combined into one, but
	    if(0 == m_meta.min) {
	      apply(count_packet_t);
	    }
	    // we choose not to do so.
	    // stage 9
	    apply(resubmit_t);
	  }
	}
      }
    }
    if(1 == m_meta.promotion) {
      /* apply(count_packet_t); */
      if(1 == m_meta.min) {
	apply(take_prom_num_t);
      }
      if(2 == m_meta.min) {
	apply(take_min_t);
      }
      if(3 == m_meta.min) {
	apply(take_rand_t);
      }
    }
  }
  else {
    // stage 0
    apply(rewrite_M1_srcip_t);
    apply(rewrite_M1_dstip_t);
    apply(rewrite_M1_proto_t);
    // stage 1
    apply(rewrite_M1_cnt_t);
    // stage 2
    apply(rewrite_M2_srcip_t);
    apply(rewrite_M2_dstip_t);
    apply(rewrite_M2_proto_t);
    // stage 3
    apply(rewrite_M2_cnt_t);
    // stage 4
    apply(rewrite_M3_srcip_t);
    apply(rewrite_M3_dstip_t);
    apply(rewrite_M3_proto_t);
    // stage 5
    apply(rewrite_M3_cnt_t);
    // stage 6
    apply(rewrite_M4_srcip_t);
    apply(rewrite_M4_dstip_t);
    apply(rewrite_M4_proto_t);
    // stage 7
    apply(rewrite_M4_cnt_t);
  }
  /* apply(count_packet_t); */
}

control egress
{
    // no operation
}
